package cn.kennylee.codehub.springboot.microtrace;

import cn.kennylee.codehub.springboot.microtrace.condition.ConditionalOnTraceEnabled;
import cn.kennylee.codehub.springboot.microtrace.feign.TraceIdFeignInterceptor;
import cn.kennylee.codehub.springboot.microtrace.filter.MicroTraceFilter;
import cn.kennylee.codehub.springboot.microtrace.filter.ReactiveMicroTraceFilter;
import cn.kennylee.codehub.springboot.microtrace.filter.ServletMicroTraceFilter;
import cn.kennylee.codehub.springboot.microtrace.thread.MdcTaskDecorator;
import feign.Feign;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * <p> 微服务请求跟踪自动配置 </p>
 * <p>Created on 2025/4/30.</p>
 *
 * @author kennylee
 * @since 0.0.1
 */
@Slf4j
@AutoConfiguration
@Configuration(proxyBeanMethods = false)
@ComponentScan(basePackages = "cn.kennylee.codehub.springboot.microtrace")
public class MicroTraceAutoConfiguration {

    @PostConstruct
    public void init() {
        log.info("微服务请求，traceId跟踪自动配置已加载");
    }

    /**
     * Servlet微服务请求跟踪过滤器
     *
     * @return Servlet微服务请求跟踪过滤器
     */
    @Bean
    @ConditionalOnClass(jakarta.servlet.Filter.class)
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @ConditionalOnMissingBean(MicroTraceFilter.class)
    @ConditionalOnTraceEnabled
    ServletMicroTraceFilter servletMicroTraceFilter(TraceProperties traceProperties) {
        return new ServletMicroTraceFilter(traceProperties);
    }

    /**
     * Reactive微服务请求跟踪过滤器
     *
     * @return Reactive微服务请求跟踪过滤器
     */
    @Bean
    @ConditionalOnClass(jakarta.servlet.Filter.class)
    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
    @ConditionalOnMissingBean(MicroTraceFilter.class)
    @ConditionalOnTraceEnabled
    ReactiveMicroTraceFilter reactiveMicroTraceFilter(TraceProperties traceProperties) {
        return new ReactiveMicroTraceFilter(traceProperties);
    }

    /**
     * 异步线程池的MDC支持
     *
     * @return MDC异步任务装饰器
     */
    @Bean
    @ConditionalOnClass(jakarta.servlet.Filter.class)
    @ConditionalOnMissingBean
    @ConditionalOnTraceEnabled
    @ConditionalOnProperty(name = "app.logging.trace.async.enabled", havingValue = "true", matchIfMissing = true)
    MdcTaskDecorator mdcTaskDecorator() {
        return new MdcTaskDecorator();
    }

    /**
     * Feign链路追踪拦截器
     */
    @Configuration
    @ConditionalOnClass(Feign.class)
    static class FeignTraceConfiguration {
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnTraceEnabled
        public TraceIdFeignInterceptor traceIdFeignInterceptor(TraceProperties traceProperties) {
            return new TraceIdFeignInterceptor(traceProperties);
        }
    }
}
